

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;
     
     
public class kanon_RecordSanitizer {
     
    String fileName;
    String parsedLine;
    int k;
    
    BufferedWriter non_k_out;
    
    ArrayList <kanon_RecordModel> records = new ArrayList<kanon_RecordModel>();
    ArrayList <kanon_RecordModel> records_copy = new ArrayList<kanon_RecordModel>();
    
    ArrayList <kanon_RecordModel> non_k_records = new ArrayList<kanon_RecordModel>();
    ArrayList <kanon_RecordModelCount> recordCounts = new ArrayList<kanon_RecordModelCount>();
    
    public kanon_RecordSanitizer(String FileName, int k) {
    	this.fileName = FileName;
    	this.k = k;
    }

    public void populateRecordCounts(int option) {
		for (int j = 0; j < records.size(); j++) {

			kanon_RecordModel fetchedRecord = records.get(j);
			
			// Step 1: Replace name and telephone no. with *			
			if (option == 1) {
				fetchedRecord.setName("*");
				fetchedRecord.setTelephone("*");
			}
			
			// Check if record already exists in recordCounts. 
			// If so, increment count otherwise add it to the list.
			int found = 0;
			
			for (int m = 0; m < recordCounts.size(); m++) {
				kanon_RecordModelCount rec = recordCounts.get(m);
				
				// Record exists with same gender, postal code and d.o.b, increment count
				kanon_RecordModel mp = rec.getRecord();
				
				if (	(mp.getGender().equals(fetchedRecord.getGender())) &&
						(mp.getDateOfBirth().equals(fetchedRecord.getDateOfBirth())) &&
						(mp.getPostalCode().equals(fetchedRecord.getPostalCode()))) {
					rec.incrementCount();
					found = 1;
					break;
				}
			}
			
			// Otherwise, not found. Add to recordCounts list		
			if (found == 0) {
				kanon_RecordModel newRecord = new kanon_RecordModel();
				newRecord.setDateOfBirth(fetchedRecord.getDateOfBirth());
				newRecord.setGender(fetchedRecord.getGender());
				newRecord.setPostalCode(fetchedRecord.getPostalCode());
				
    			kanon_RecordModelCount fetchedRecordCount = new kanon_RecordModelCount(newRecord, 1);			
				recordCounts.add(fetchedRecordCount);    				
			}    			
		}    	
    }
    
    public void kAnonymizeRecords(int option) {
    	
		for (int a=0; a < records.size(); a++) {
			kanon_RecordModel mp = records.get(a);
			
			for(int n=0; n < recordCounts.size(); n++) {	
				kanon_RecordModel moo = recordCounts.get(n).getRecord();
				
	    		// RecordCounts where the count is < k are those that do not hold k-anonymity
				if (	(mp.getGender().equals(moo.getGender())) &&
						(mp.getDateOfBirth().equals(moo.getDateOfBirth())) &&
						(mp.getPostalCode().equals(moo.getPostalCode()))
						&& (recordCounts.get(n).getCount() < k)) {
					
					// Step 2
					if (option == 1) {
						String DateOfBirth = records.get(a).getDateOfBirth();
						String[] dob_split = DateOfBirth.split("-");
						records.get(a).setDateOfBirth("*-"+dob_split[1]+"-"+dob_split[2]);
					}
					// Step 3
					else if (option == 2) {
    					String DateOfBirth = records.get(a).getDateOfBirth();
    					String[] dob_split = DateOfBirth.split("-");
    					records.get(a).setDateOfBirth("*-*-"+dob_split[2]);						
					}
					// Step 4
					else if (option == 3) {
    					String PostalCode = records.get(a).getPostalCode();
    					String[] postalCode_split = PostalCode.split(" ");
    					records.get(a).setPostalCode(postalCode_split[0]+" *");						
					}
					// Step 5
					else if (option == 4) {
						// Write to non k-anonymity file the original records not satisfying k-anonymity
						try {
							non_k_out.write(records_copy.get(a).toString());
						} catch (Exception e) {
							// TODO: handle exception
						}
					}
					break;
				}
			}					
		}
		recordCounts.clear();
    }
    
    public void ReadFile() {
    	try {
    		
    		BufferedReader br = new BufferedReader(new FileReader(fileName));
    		
    		FileWriter fstream = new FileWriter("anonymized.csv");    		
    		BufferedWriter out = new BufferedWriter(fstream);
    		
    		FileWriter non_k_fstream = new FileWriter("non-kanonymized.csv");    		
    		non_k_out = new BufferedWriter(non_k_fstream);

    		int lineNumber = 1;
    		
    		// Read file line by line
    		while( (parsedLine = br.readLine()) != null) {
    			// Write column line to both output files
			    if (lineNumber == 1) {
			    	out.write(parsedLine + "\n");
			    	non_k_out.write(parsedLine + "\n");
			    }
			    //Put each record line into serializable object lists: records and records_copy
			    else {    
			    	String[] recordElements = parsedLine.split(",");
		    		
		    		kanon_RecordModel record = new kanon_RecordModel(	recordElements[0],
		    												recordElements[1],
		    												recordElements[2],
		    												recordElements[3],
		    												recordElements[4],
		    												recordElements[5]);
		    		records.add(record);
		    		
		    		kanon_RecordModel record_copy = new kanon_RecordModel(	recordElements[0],
							recordElements[1],
							recordElements[2],
							recordElements[3],
							recordElements[4],
							recordElements[5]);
		    		
		    		records_copy.add(record_copy);
			    }
    			lineNumber++;
    		}
			
    		// Step 1: option == 1 , Replace name and telephone with '*'
    		populateRecordCounts(1);
    		
    		// Step 2: Replace the day in d.o.b with '*' if condition satisfied    		
    		kAnonymizeRecords(1);
    		    		
    		// Step 3: Replace the month in d.o.b with '*' if condition satisfied
    		populateRecordCounts(2);
    		kAnonymizeRecords(2);

    		// Step 4: Replace second part of postal code with '*' if condition satisfied
    		populateRecordCounts(2);
    		kAnonymizeRecords(3);
    		
    		// Step 5 : Generate non-k-anonymity records 		
    		populateRecordCounts(2);
    		kAnonymizeRecords(4);  		
    		
    		// Write k-anonymity records to file
    		for (int z=0; z < records.size(); z++) {
    			out.write(records.get(z).toString());
    		}
    		    		
    		out.close();
    		non_k_out.close();
    		
    	} catch (FileNotFoundException e) {
		    // TODO Auto-generated catch block
		    e.printStackTrace();
		    } catch (IOException e) {
		    // TODO Auto-generated catch block
		    e.printStackTrace();
		    }
    }
}